/**
 * @Project: LizhiFM
 * @Author: squll
 * @Date: 2013-10-8
 * @Copyright: (c) 2013 广州市一把伞网络科技有限公司 All rights reserved.
 */

package com.hubujun.driverlicense.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;


import com.hubujun.driverlicense.util.Ln;
import com.hubujun.driverlicense.util.Util;

import junit.framework.Assert;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;

public class SqliteDB implements ContentProviderDB {

	private SQLiteDatabaseHelper mHelper;

	private int ticket;

	public static boolean isEmpty(String str) {
		return str == null || str.length() <= 0;
	}

	public static String escape(String sql) {
		String value;
		if (isEmpty(sql))
			value = "";
		else
			value = DatabaseUtils.sqlEscapeString(sql);

		return value;
	}

	public boolean openDatebase(String dbCachePath, String enDbCachePath, int version, HashMap<String, BuildTable> interfaces) {
		Assert.assertTrue("create SqliteDB dbCachePath == null ", !isEmpty(dbCachePath));
		Ln.d("InitDb : %s", dbCachePath);
		close();
		mHelper = SQLiteDatabaseHelper.openOrCreateDatabase(dbCachePath);
		if (mHelper == null)
			return false;
		try {
			int curVersion = mHelper.getVersion();
			if (curVersion != version) {
				int ticket = beginTransaction();
				try {
					if (curVersion == 0) {
						for (BuildTable t : interfaces.values()) {
							Ln.d("begin to create table %s sql", t.getName());
							for (String sql : t.onCreate()) {
								mHelper.execSQL(sql);
							}
						}
					} else if (version > curVersion) {

						Cursor c = mHelper.query("sqlite_master", new String[] { "name" }, "type=?", new String[] { "table" }, null);
						ArrayList<String> tables = new ArrayList<String>();
						for (int i = -1; ++i < c.getCount();) {
							if (c.moveToPosition(i)) {
								tables.add(c.getString(0));
							}
						}
						c.close();

						for (BuildTable t : interfaces.values()) {
							if (!tables.contains(t.getName())) {
								Ln.d("begin to create table %s sql", t.getName());
								for (String sql : t.onCreate()) {
									mHelper.execSQL(sql);
								}
							}
						}

						for (BuildTable t : interfaces.values()) {
							if (tables.contains(t.getName())) {
								Ln.d("begin to upgrade table %s sql", t.getName());
								t.onUpdate(this, curVersion, version);
							}
						}
						tables.clear();

					}
					mHelper.setVersion(version);
					setTransactionSuccessful(ticket);
				} finally {
					endTransaction(ticket);
				}
			}
			return true;
		} catch (Exception e) {
			Ln.e(e, "openDatebase fail");
		}

		return false;
	}

	public void close() {
		if (mHelper != null) {
			Ln.d("close db now: inTrans: %s", mHelper.inTransaction());
			if (mHelper.inTransaction()) {
				mHelper.setTransactionSuccessful();
				mHelper.endTransaction();
			}
			mHelper.close();
			mHelper = null;
		}
	}

	@Override
	public int update(String table, ContentValues values, String where, String[] selectionArgs) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.update(table, values, where, selectionArgs);
		} catch (Exception e) {
			Ln.e(e, "update Error :");
		}
		return -1;
	}

	@Override
	public int delete(String table, String where, String[] selectionArgs) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.delete(table, where, selectionArgs);
		} catch (Exception e) {
			Ln.e(e, "delete Error :");
		}
		return -1;
	}

	@Override
	public long insert(String table, String nullColumnHack, ContentValues values) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.insert(table, nullColumnHack, values);
		} catch (Exception e) {
			Ln.e(e, "insert Error :");
			e.printStackTrace();
		}
		return -1;
	}

	@Override
	public Cursor rawQuery(String sql, String[] selectionArgs) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.rawQuery(sql, selectionArgs);
		} catch (Exception e) {
			Ln.e(e);
		}
		return new MatrixCursor(new String[] { "" }, 1);
	}

	@Override
	public Cursor query(String table, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.query(table, projection, selection, selectionArgs, sortOrder);
		} catch (Exception e) {
			Ln.e(e);
		}
		return new MatrixCursor(new String[] { "" }, 1);
	}

	@Override
	public long replace(String table, String nullColumnHack, ContentValues initialValues) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.replace(table, nullColumnHack, initialValues);
		} catch (Exception e) {
			Ln.e(e, "replace Error :");
		}
		return -1;
	}

	@Override
	public boolean execSQL(String sql) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			Assert.assertTrue("sql is null", sql != null);
			mHelper.execSQL(sql);
			return true;
		} catch (Exception e) {
			Ln.e(e, "execSQL Error :");
		}
		return false;
	}

	public int beginTransaction() {
		if (ticket == 0) {
			try {
				Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
				mHelper.beginTransaction();
				ticket = ((int) Util.curTime()) >>> 1;
				Ln.d("beginTransaction succ ticket:%d", ticket);
				return ticket;
			} catch (Exception e) {
				Ln.e(e, "beginTransaction Error :");
			}
		} else {
			Ln.d("ERROR beginTransaction transaction Ticket: %d", ticket);
		}

		return -1;

	}

	public int setTransactionSuccessful(int i) {
		if (ticket == i) {
			try {
				Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
				mHelper.setTransactionSuccessful();
				Ln.d("setTransactionSuccessful succ transactionTicket: %d", ticket);
				return 0;
			} catch (Exception e) {
				Ln.e(e, "setTransactionSuccessful Error :");
			}
		} else {
			Ln.d("ERROR setTransactionSuccessful ticket: %d, transactionTicket: %d", i, ticket);
		}
		return -1;
	}

	public int endTransaction(int i) {
		if (i == ticket) {
			try {
				Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
				mHelper.endTransaction();
				Ln.d("endTransaction succ transactionTicket:%d", ticket);
				ticket = 0;
			} catch (Exception e) {
				Ln.e(e, "endTransaction Error :");
			}
		} else {
			Ln.d("ERROR endTransaction ticket:%d, transactionTicket:%d", i, ticket);
		}

		return -1;
	}

	@Override
	public Cursor query(String table, String[] projection, String selection, String[] selectionArgs, String sortOrder, String limit) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.query(table, projection, selection, selectionArgs, sortOrder, limit);
		} catch (Exception e) {
			Ln.e(e);
		}
		return new MatrixCursor(new String[] { "" }, 1);
	}

	@Override
	public Cursor query(String table, String[] projection, String selection, String[] selectionArgs, String groupBy, String sortOrder, String limit) {
		try {
			Assert.assertTrue("SQLiteDatabase is null", mHelper != null);
			return mHelper.query(table, projection, selection, selectionArgs, groupBy, sortOrder, limit);
		} catch (Exception e) {
			Ln.e(e);
		}
		return new MatrixCursor(new String[] { "" }, 1);
	}

}
